# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: inkyu

import datetime
import logging

import tabulate

from coin.exchange.shared.kr_rest.currency import SharedCurrency
from coin.strategy.hk_hard_arb.products import NativeProducts


class IntraArbProduct(object):
  def __init__(self, base, native_products):
    self.base = base
    self.native_products = native_products
    for native_product in native_products:
      assert base.currency == native_product.base.currency, (base, native_product.base)


class IntraArbProducts(object):
  def __init__(self, quote0_currency_str, quote1_currency_str, base_currencies_str, ProductType):
    self.shared = NativeProducts.FromSharedStrCurrency('DUMMY', base_currencies_str)
    self.native_0 = NativeProducts.FromTypedStrCurrency(quote0_currency_str,
                                                        base_currencies_str,
                                                        ProductType)
    self.native_1 = NativeProducts.FromTypedStrCurrency(quote1_currency_str,
                                                        base_currencies_str,
                                                        ProductType)
    self.quote_currencies = [
        self.native_0.quote_currency,
        self.native_1.quote_currency,
    ]
    self._arb_product_list = [
        IntraArbProduct(self.native_0.base_currencies[idx],
                        [self.native_0.products[idx], self.native_1.products[idx]])
        for idx in range(len(base_currencies_str))
    ]
    self._symbol_map = {symbol: idx for idx, symbol in enumerate(base_currencies_str)}

  def by_idx(self, idx):
    return self._arb_product_list[idx]

  def by_symbol(self, symbol):
    return self.by_idx(self._symbol_map[symbol])


class IntraArbBalance(object):
  def __init__(self, base_total, base_reserve, quote0_total, quote0_reserve, quote1_total):
    pass


class IntraArbInfoPrinter(object):
  def __init__(self, arb_products, arb_constraints):
    self._logger = logging.getLogger(__name__)

    self._ogs = ogs
    self._quote_currencies = quote_currencies
    assert len(self._ogs) == len(self._quote_currencies)
    self._base_currencies = base_currencies
    self._ogs_name = [og._og_info.CurrencyType._exchange for og in ogs]

  def print_balance(self):
    table = []
    for i, cur in enumerate(self._quote_currencies):
      bals = [og.get_balance(cur.currency) if i == j else 0 for j, og in enumerate(self._ogs)]
      table.append(['*', cur.currency, sum(bals)] + bals)
    for cur in self._base_currencies:
      # use cur.currency, not cur, as ogs do not have same type
      bals = [og.get_balance(cur.currency) for og in self._ogs]
      table.append(['*', cur.currency, sum(bals)] + bals)

    self._logger.info(
        '----- Balance:\n* %s\n%s' %
        (str(datetime.datetime.now()),
         tabulate.tabulate(
             table, headers=['*', 'Currency', 'Total'] + self._ogs_name, floatfmt=".6f")))

  def get_currency_balance(self, currency, reserve_balance):
    assert type(currency) == SharedCurrency
    # use cur.currency, not cur, as ogs do not have same type
    base_bals = [og.get_balance(currency.currency) for og in self._ogs]

    return IntraArbBalance(base_balances=base_bals,
                           quote_balances=None,
                           base_reserve=reserve_balance)

  def get_balance(self, arb_product, reserve_balance):
    assert type(arb_product) == IntraArbProduct
    # use cur.currency, not cur, as ogs do not have same type
    base_bals = [og.get_balance(arb_product.base.currency) for og in self._ogs]
    quote_bals = []
    for og, quote_currency in zip(self._ogs, self._quote_currencies):
      quote_bals.append(og.get_balance(quote_currency.currency))

    return IntraArbBalance(base_balances=base_bals,
                           quote_balances=quote_bals,
                           base_reserve=reserve_balance)

  def check_balances(self, og):
    base_totals = []
    for currency in base_currencies:
      base_bals = [og.get_balance(currency) for og in self._ogs]
      base_totals.append(sum(base_bals))
    for currency in quote_currencies:
      quote_bals = [og.get_balance(currency) for og in self._ogs]
      quote_totals.append(sum(quote_totals))
